package com.csun.cmny.provider.service.impl;

import com.csun.cmny.base.dto.LoginAuthDto;
import com.csun.cmny.base.dto.UserTokenDto;
import com.csun.cmny.base.enums.ErrorCodeEnum;
import com.csun.cmny.core.support.BaseService;
import com.csun.cmny.provider.dao.UacStaffMapper;
import com.csun.cmny.provider.dao.UacUserTokenMapper;
import com.csun.cmny.provider.model.constant.EmpConstant;
import com.csun.cmny.provider.model.domain.*;
import com.csun.cmny.provider.model.dto.staff.ModifyPwdDto;
import com.csun.cmny.provider.model.dto.staff.StaffDto;
import com.csun.cmny.provider.model.dto.staff.StaffQueryDto;
import com.csun.cmny.provider.model.enums.*;
import com.csun.cmny.provider.model.exceptions.UacBizException;
import com.csun.cmny.provider.model.vo.StaffVO;
import com.csun.cmny.provider.resolver.CmnyMessageSource;
import com.csun.cmny.provider.service.*;
import com.csun.cmny.provider.utils.Md5Util;
import com.csun.cmny.util.PublicUtil;
import com.csun.cmny.util.RedisKeyUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.base.Preconditions;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
@Transactional
public class UacStaffServiceImpl extends BaseService<UacStaff> implements UacStaffService {
    
    @Resource
    private UacStaffMapper uacStaffMapper;
    @Resource
    private UacUserService uacUserService;
    @Resource
    private UacEmpService uacEmpService;
    @Resource
    private UacGroupUserService uacGroupUserService;
    @Resource
    private UacRoleService uacRoleService;
    @Resource
    private UacRoleUserService uacRoleUserService;
    @Resource
    private UacUserTokenService uacUserTokenService;
    @Resource
    private UacUserTokenMapper uacUserTokenMapper;
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private CmnyMessageSource cmnyMessageSource;
    @Resource
    private OmcRpcService omcRpcService;
    @Resource
    private UacStaffStatusService statusService;

    
    @Override
    public Integer addStaff(StaffDto staffDto, LoginAuthDto loginAuthDto) {
        // 校验登录账号
        UacUser uacUserQuery = new UacUser();
        uacUserQuery.setLoginName(staffDto.getLoginName());
        int result = uacUserService.selectCount(uacUserQuery);
        if (result > 0) {
            // 用户已经存在
            throw new UacBizException(ErrorCodeEnum.UAC10011012);
        }

        // 校验身份证号码
        uacUserQuery = new UacUser();
        uacUserQuery.setIdCard(staffDto.getIdCard());
        result = uacUserService.selectCount(uacUserQuery);
        if (result > 0) {
            // 身份证已经存在
            throw new UacBizException(ErrorCodeEnum.UAC10011044);
        }

        // 校验手机号
        uacUserQuery = new UacUser();
        uacUserQuery.setMobileNo(staffDto.getMobileNo());
        result = uacUserService.selectCount(uacUserQuery);
        if (result > 0) {
            // 手机号已经存在
            throw new UacBizException(ErrorCodeEnum.UAC10011013);
        }

        // 3.添加用户
        UacUser uacUser = new UacUser();
        BeanUtils.copyProperties(staffDto, uacUser);

        // 4.更新用户身份证信息(身份证, 性别, 年龄)
        uacEmpService.setIdCard(uacUser);

        // 5.员工使用系统默认密码
        uacUser.setLoginPwd(Md5Util.encrypt(EmpConstant.EMP_DEFAULT_PWD));
        uacUser.setType(UacUserTypeEnum.STAFF_EMP.getKey());
        uacUser.setUserSource(UacUserSourceEnum.INSERT.getKey());
        uacUser.setStatus(UacEmpStatusEnum.ENABLE.getType());
        uacUser.setCreator(loginAuthDto.getUserName());
        uacUser.setCreatorId(loginAuthDto.getUserId());
        uacUser.setLastOperator(loginAuthDto.getUserName());
        uacUser.setLastOperatorId(loginAuthDto.getUserId());
        result = uacUserService.save(uacUser);
        if (result < 1) {
            throw new UacBizException(ErrorCodeEnum.UAC10018001);
        }

        // 6.添加服务人员
        UacStaff uacStaff = new UacStaff();
        BeanUtils.copyProperties(staffDto, uacStaff);

        uacStaff.setUserId(uacUser.getId());
        uacStaff.setCreator(loginAuthDto.getUserName());
        uacStaff.setCreatorId(loginAuthDto.getUserId());
        uacStaff.setLastOperator(loginAuthDto.getUserName());
        uacStaff.setLastOperatorId(loginAuthDto.getUserId());
        uacStaffMapper.insertSelective(uacStaff);
        if (result < 1) {
            throw new UacBizException(ErrorCodeEnum.UAC10018001);
        }

        // 3 绑定组织关系
        UacGroupUser uacGroupUser = new UacGroupUser();
        uacGroupUser.setGroupId(loginAuthDto.getGroupId());
        uacGroupUser.setUserId(uacUser.getId());
        uacGroupUserService.save(uacGroupUser);

        // 设置用户角色
        UacRole uacRole = uacRoleService.findByRoleCode(UacRoleCodeEnum.STAFF.getCode());
        if (PublicUtil.isEmpty(uacRole)) {
            throw new UacBizException(ErrorCodeEnum.UAC10013011);
        }
        uacRoleUserService.saveRoleUser(uacUser.getId(), uacRole.getId());

        return result;
    }

    @Override
    public Integer updateStaff(StaffDto staffDto, LoginAuthDto loginAuthDto) {
        // 校验志愿者是否存在
        UacStaff uacStaffQuery = uacStaffMapper.selectByPrimaryKey(staffDto.getId());
        if (PublicUtil.isEmpty(uacStaffQuery)) {
            throw new UacBizException(ErrorCodeEnum.UAC10018002);
        }

        boolean isUserNameRefresh = false;
        boolean isTokenRefresh = false;
        Long userId = uacStaffQuery.getUserId();

        UacUser uacUser = uacUserService.selectByKey(userId);
        if (PublicUtil.isEmpty(uacUser)) {
            throw new UacBizException(ErrorCodeEnum.UAC10011047);
        }
        String loginName = uacUser.getLoginName();

        Example example = new Example(UacUser.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andNotEqualTo("id", userId);

        // 更新手机号
        if (StringUtils.isNoneEmpty(staffDto.getMobileNo())) {
            if (!uacUserService.checkMobileNo(userId, staffDto.getMobileNo())) {
                // 存在重复的手机号
                throw new UacBizException(ErrorCodeEnum.UAC10011013);
            }
            uacUser.setMobileNo(staffDto.getMobileNo());
        }
        // 更新登录账户
        if (StringUtils.isNotEmpty(staffDto.getLoginName())
                && !uacUser.getLoginName().equals(staffDto.getLoginName())) {
            if (!uacUserService.checkLoginName(userId, staffDto.getLoginName())) {
                throw new UacBizException(ErrorCodeEnum.UAC10011012);
            }

            uacUser.setLoginName(staffDto.getLoginName());
            isTokenRefresh = true;
        }

        // 更新姓名
        if (StringUtils.isNoneEmpty(staffDto.getUserName())) {
            uacUser.setUserName(staffDto.getUserName());
            isUserNameRefresh = true;
        }
        // 更新用户身份证信息(身份证, 性别, 年龄)
        if (StringUtils.isNotEmpty(staffDto.getIdCard())) {
            // 校验身份证号码是否已经存在
            if (!uacUserService.checkIdCard(userId, staffDto.getIdCard())) {
                throw new UacBizException(ErrorCodeEnum.UAC10011044);
            }

            uacUser.setIdCard(staffDto.getIdCard());
            uacEmpService.setIdCard(uacUser);
        }
        uacUser.setUpdateInfo(loginAuthDto);
        int result = uacUserService.updateUser(uacUser);
        if (result < 1) {
            throw new UacBizException(ErrorCodeEnum.UAC10011026, userId);
        }

        if (isTokenRefresh) {
            // 刷新token
            /**
             * @date    2019-09-04
             * @author  chisj
             * @desc    修改登录名后，需要将之前的token清除
             */
            uacUserTokenService.restToken(loginName);
        }

        // 更新志愿者信息
        BeanUtils.copyProperties(staffDto, uacStaffQuery);
        uacStaffQuery.setUpdateInfo(loginAuthDto);
        result = uacStaffMapper.updateByPrimaryKeySelective(uacStaffQuery);
        if (result < 1) {
            throw new UacBizException(ErrorCodeEnum.UAC10018003);
        }

        // 判断是否需要更新token中的用户名
        if (!isTokenRefresh && isUserNameRefresh) {
            // 根据登录名获取所有在线的access_token
            UacUserToken userToken = new UacUserToken();
            userToken.setStatus(UacUserTokenStatusEnum.ON_LINE.getStatus());
            userToken.setUserId(userId);

            List<UacUserToken> userTokenList = uacUserTokenMapper.selectTokenList(userToken);
            for (UacUserToken token : userTokenList) {
                String redisKey = RedisKeyUtil.getAccessTokenKey(token.getAccessToken());
                UserTokenDto userTokenDto = (UserTokenDto) redisTemplate.opsForValue().get(redisKey);
                if (PublicUtil.isNotEmpty(userTokenDto)) {
                    userTokenDto.setUserName(uacUser.getUserName());
                    long timeout = redisTemplate.getExpire(redisKey);

                    // 存入redis数据库
                    updateRedisUserToken(token.getAccessToken(), (int)timeout, userTokenDto);
                }
            }
        }

        return result;
    }

    private void updateRedisUserToken(String accessToken, int accessTokenValidateSeconds, UserTokenDto userTokenDto) {
        redisTemplate.opsForValue().set(RedisKeyUtil.getAccessTokenKey(accessToken), userTokenDto, accessTokenValidateSeconds, TimeUnit.SECONDS);
    }

    @Override
    public Integer deleteStaffById(Long id) {
        // 校验志愿者是否存在
        UacStaff uacStaffQuery = uacStaffMapper.selectByPrimaryKey(id);
        if (PublicUtil.isEmpty(uacStaffQuery)) {
            throw new UacBizException(ErrorCodeEnum.UAC10018002);
        }


        //校验服务人员名下是否有未完成订单
        Integer have=omcRpcService.selectHaveUnfinishedOrderNumbers(uacStaffQuery.getUserId());

        if (have>0){
            throw new UacBizException(ErrorCodeEnum.UAC10019002);
        }

        //校验服务人员是否是专家
        Integer isSpecialist = omcRpcService.isSpecialist(id);
        if (isSpecialist>0){
            throw new UacBizException(ErrorCodeEnum.UAC10019003);
        }

        // 删除用户
        uacUserService.deleteUserById(uacStaffQuery.getUserId());

        // 删除角色
        UacRole uacRole = uacRoleService.findByRoleCode(UacRoleCodeEnum.STAFF.getCode());
        if (PublicUtil.isNotEmpty(uacRole)) {
            UacRoleUser uacRoleUser = new UacRoleUser();
            uacRoleUser.setRoleId(uacRole.getId());
            uacRoleUser.setUserId(uacStaffQuery.getUserId());
            uacRoleUserService.delete(uacRoleUser);
        }

        // 删除group
        UacGroupUser uacGroupUser = new UacGroupUser();
        uacGroupUser.setUserId(uacStaffQuery.getUserId());
        uacGroupUserService.delete(uacGroupUser);

        //删除上下线日志

        int delete = statusService.deleteByStaffId(id);



        return uacStaffMapper.deleteByPrimaryKey(id);
    }

    @Override
    public PageInfo listPage(StaffQueryDto staffQueryDto) {


        PageHelper.startPage(staffQueryDto.getPageNum(), staffQueryDto.getPageSize());
        List<StaffVO> staffVOList = uacStaffMapper.listPage(staffQueryDto);

        return new PageInfo<>(staffVOList);
    }

    @Override
    public Integer modifyPwd(ModifyPwdDto modifyPwdDto, LoginAuthDto loginAuthDto) {

        // 校验密码和确认密码是否一致
        Preconditions.checkArgument( modifyPwdDto.getPassword()
                        .equals( modifyPwdDto.getConfirmPwd()),
                cmnyMessageSource.getMessage("staff.password.confirm.equal", null));

        // 校验志愿者是否存在
        UacStaff uacStaff =  uacStaffMapper.selectByPrimaryKey( modifyPwdDto.getId());
        if (PublicUtil.isEmpty(uacStaff)) {
            throw new UacBizException(ErrorCodeEnum.UAC10018002);
        }

        // 获取用户信息
        UacUser uacUser = uacUserService.selectByKey(uacStaff.getUserId());
        if (PublicUtil.isEmpty(uacUser)) {
            throw new UacBizException(ErrorCodeEnum.UAC10011003, uacStaff.getUserId());
        }

        // 校验密码是否一致
        if (Md5Util.matches( modifyPwdDto.getPassword(), uacUser.getLoginPwd())) {
            throw new UacBizException(ErrorCodeEnum.UAC10011036);
        }

        // 更新密码
        UacUser uacUserUpt = new UacUser();
        String newEncrypt = Md5Util.encrypt( modifyPwdDto.getPassword());
        uacUserUpt.setId(uacUser.getId());
        uacUserUpt.setLoginPwd(newEncrypt);
        uacUserUpt.setUpdateInfo(loginAuthDto);
        Integer result = uacUserService.updateUser(uacUserUpt);

        // 刷新token
        uacUserTokenService.restToken(uacUser.getLoginName());

        return result;
    }

    @Override
    public UacStaff selectByUserId(Long userId) {
            return uacStaffMapper.selectByUserId(userId);
        }

    @Override
    public UacStaff selectByUserIdTest(Long userId) {
        return uacStaffMapper.selectByUserIdTest(userId);
    }

    @Override
    public PageInfo selectStaffByNotSpecoalist(StaffQueryDto staffQueryDto) {

        List<Long> specialistStaffIds=omcRpcService.selectStaffIdBySpecialist();

        PageHelper.startPage(staffQueryDto.getPageNum(), staffQueryDto.getPageSize());
        List<StaffVO> staffVOList = uacStaffMapper.selectStaffByNotSpecoalist(staffQueryDto,specialistStaffIds);

        return new PageInfo<>(staffVOList);
    }

    @Override
    public UacStaff selectStaffByUserId(Long userId) {
        return uacStaffMapper.selectStaffByUserId(userId);
    }


}
